﻿package igz.fleaxy.ui.form.input
{
	import flash.display.DisplayObject;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.filters.DropShadowFilter;
	import flash.utils.Timer;
	import igz.fleaxy.Fleaxy;
	import igz.fleaxy.ui.form.input.Input;
	import igz.fleaxy.ui.ButtonUi;
	import igz.fleaxy.util.Convert;
	import igz.fleaxy.util.ObjectUtil;

	
	/**
	 *   Inputo ocupado de admitir solo valores numéricos.
	 * 
	 * @author Intelygenz | www.intelygenz.com
	 */
	public class InputNumericUi extends Sprite {

		protected var _Settings:Object;
		
		protected var _Input:Input;
		public function get $Input() : Input {
			return _Input;
		}
		
		protected var _BtnUp:ButtonUi;
		protected var _BtnDown:ButtonUi;
		
		protected var _TimerDown:Timer;
		protected var _TimerUp:Timer;
		
		/**
		 * Componente input númerico con botones incrementar que permite introducir 
		 * 
		 * @param	p_name nombre del elemento
		 * @param	p_settings  { "restringedValues" : { "minValue" : NaN
											           , "maxValue" : NaN
											           }
						  , "inputType" : InputType.$DECIMAL
						  , "inputStyle" : { "inputTextStyle": "" }
						  , "arrowSize" : NaN // Si no se especifica, se calcula en función del tamaño del input
						  , "arrowColor" : 0x000000
						  , "arrowAlpha" : 0.6
						  , "stepValue" : 1 // Number
						  , "digitsToRound" : 2 // uint
						  , "background" : 0xFFFFFF
						  , "border" : 0x000000
			};
		 * 
		 * 
		 * 
		 */
		public function InputNumericUi(p_name:String, p_settings:Object = null) {
			_Settings = { "restringedValues" : { "minValue" : NaN
											   , "maxValue" : NaN
											  }
						  , "inputType" : InputType.$DECIMAL
						  , "inputStyle" : { "inputTextStyle": "" }
						  , "arrowSize" : NaN // Si no se especifica, se calcula en función del tamaño del input
						  , "arrowColor" : 0x000000
						  , "arrowAlpha" : 0.6
						  , "stepValue" : 1 // Number
						  , "digitsToRound" : 2 // uint
						  , "background" : 0xFFFFFF
						  , "border" : 0x000000
			};
			ObjectUtil.$Merge( p_settings, _Settings );

			_Input = new Input(p_name, _Settings);
			_Input.$TextUi.text = isNaN( _Settings["restringedValues"]["minValue"] ) ? "0": Convert.$ToString(_Settings["restringedValues"]["minValue"]);
			addChild(_Input);

			_Settings["arrowSize"] = (_Input.height / 2) - 5;
			
			_BtnUp = new ButtonUi("", _BtnUp_OnClick, {"icon":_CreateArrowUp(),"marginInternal":0,"marginLeft":2,"marginTop":2});
			addChild(_BtnUp);
			
			_BtnDown = new ButtonUi("", _BtnDown_OnClick, {"icon":_CreateArrowDown(),"marginInternal":0,"marginLeft":2,"marginTop":2});
			addChild(_BtnDown);
			
			_TimerDown = new Timer(150);
			_TimerUp = new Timer(150);
			
			_Recolocate();
			
			$Enable();
		}
		
		/**
		 * Recoloca el input
		 */
		protected function _Recolocate() : void {
			_BtnUp.x = _Input.$TextUi.width + 2;
			
			_BtnDown.x = _BtnUp.x;
			_BtnDown.y = _BtnUp.y + _BtnUp.height + 1;
		}
		
		
		/**
		 * Crea la flecha inferior para decrementar el valor
		 * @return Devuelve el DisplayObj con esta flecha
		 */
		protected function _CreateArrowDown () : DisplayObject {
			var arrow : Shape = new Shape();
			arrow.graphics.beginFill(_Settings["arrowColor"], _Settings["arrowAlpha"]);
			arrow.graphics.moveTo(0, 0);
			arrow.graphics.lineTo(_Settings["arrowSize"], 0);
			arrow.graphics.lineTo(_Settings["arrowSize"] / 2, _Settings["arrowSize"]);
			arrow.graphics.lineTo(0, 0);
			arrow.graphics.endFill();
			
			return arrow;
		}
		
		/**
		 * Crea la flecha superior para incrementar el valor
		 * @return Devuelve el DisplayObj con esta flecha
		 */		
		protected function _CreateArrowUp () : DisplayObject {
			var arrow : Shape = new Shape();
			arrow.graphics.beginFill(_Settings["arrowColor"], _Settings["arrowAlpha"]);
			arrow.graphics.moveTo(0, _Settings["arrowSize"]);
			arrow.graphics.lineTo(_Settings["arrowSize"], _Settings["arrowSize"]);
			arrow.graphics.lineTo(_Settings["arrowSize"] / 2, 0);
			arrow.graphics.lineTo(0, _Settings["arrowSize"]);
			arrow.graphics.endFill();
			
			return arrow;
		}

		/**
		 * Incrementa el valor
		 */
		protected function _Increase() : void {

			var num:Number = _GetValueNumber(Convert.$ToNumber(_Input.$TextUi.text));
			num += _Settings["stepValue"];
			_Input.$TextUi.text = Convert.$ToString(_GetValueNumber(num));
			_CheckRestringedValues();
			
			dispatchEvent( new Event(Event.CHANGE) );
		}
		
		/**
		 * Decrementa el valor
		 */
		protected function _Decrease() : void {
			var num:Number = _GetValueNumber(Convert.$ToNumber(_Input.$TextUi.text));
			num -= _Settings["stepValue"];
			_Input.$TextUi.text = Convert.$ToString(_GetValueNumber(num));
			_CheckRestringedValues();
			
			dispatchEvent( new Event(Event.CHANGE) );
		}
		
		/**
		 * Devuelve el valor, si ha de ser redondeando lo redondea
		 * @param	p_num numero a devolver
		 * @return  valor ya tratado
		 */
		protected function _GetValueNumber ( p_num : Number ) : Number {
			var round : uint = _Settings["digitsToRound"] * 10;
			var num:Number = Math.round( p_num * round ) / round;

			return num;
		}
		
		/**
		 * comprueba que el valor no está fuera de rango
		 */
		protected function _CheckRestringedValues () : void {
			var dashPosInit : Number = _Input.$TextUi.text.indexOf("-");
			var dashPosLast : Number = _Input.$TextUi.text.lastIndexOf("-");

			if ( dashPosLast != -1 && dashPosLast != 0 ) {
				_Input.$TextUi.text = _Input.$TextUi.text.replace("-", "");
				if ( dashPosInit == 0 ) {
					_Input.$TextUi.text = "-"+_Input.$TextUi.text;
				}
			}

			if ( _Input.$TextUi.text != "" && _Input.$TextUi.text != "-" ) {
				var num : Number = Convert.$ToNumber( _Input.$TextUi.text );

				var maxValue : Number = _Settings["restringedValues"]["maxValue"];
				var minValue : Number = _Settings["restringedValues"]["minValue"];
				if ( !isNaN(maxValue) && (num > maxValue) ) {
					num = maxValue;
				}
				else if ( !isNaN(minValue) && (num < minValue) ) {
					num = minValue;
				}
				_Input.$TextUi.text = Convert.$ToString( num );
			}
		}

		protected function _Input_OnChange ( p_event:Event ) : void {
			_CheckRestringedValues();
			
			dispatchEvent( new Event(Event.CHANGE) );
		}

		//
		// BtnDown
		//
		protected function _BtnDown_OnMouseDown ( p_event:MouseEvent ):void {
			_TimerDown.start();
		}
		
		protected function _BtnDown_OnMouseUp( p_event:MouseEvent ):void {
			_TimerDown.stop();
		}

		protected function _BtnDown_OnClick():void {
			_Decrease();
		}
		
		protected function _TimerDown_OnTimer( p_event:TimerEvent ):void {
			_Decrease();
		}

		//
		// BtnUp
		//
		protected function _BtnUp_OnMouseDown( p_event:MouseEvent ) : void {
			_TimerUp.start();
		}

		protected function _BtnUp_OnMouseUp( p_event:MouseEvent ) : void {
			_TimerUp.stop();
		}
		
		protected function _BtnUp_OnClick():void {
			_Increase();
		}
		
		protected function _TimerUp_OnTimer( p_event:TimerEvent ) : void {
			_Increase();
		}
		
		public function $Enable () : void {
			_BtnUp.addEventListener(MouseEvent.MOUSE_DOWN, _BtnUp_OnMouseDown);
			_BtnUp.addEventListener(MouseEvent.MOUSE_UP, _BtnUp_OnMouseUp);
			_BtnUp.addEventListener(MouseEvent.MOUSE_OUT, _BtnUp_OnMouseUp);
			
			_BtnDown.addEventListener(MouseEvent.MOUSE_DOWN, _BtnDown_OnMouseDown);
			_BtnDown.addEventListener(MouseEvent.MOUSE_UP, _BtnDown_OnMouseUp);
			_BtnDown.addEventListener(MouseEvent.MOUSE_OUT, _BtnDown_OnMouseUp);
			
			_TimerDown.addEventListener(TimerEvent.TIMER, _TimerDown_OnTimer);
			_TimerUp.addEventListener(TimerEvent.TIMER, _TimerUp_OnTimer);
			
			_Input.$TextUi.addEventListener(Event.CHANGE, _Input_OnChange);
			
			_BtnDown.$Enable();
			_BtnUp.$Enable();
			_Input.$Enable();
		}
		
		public function $Disable () : void {
			_BtnUp.removeEventListener(MouseEvent.MOUSE_DOWN, _BtnUp_OnMouseDown);
			_BtnUp.removeEventListener(MouseEvent.MOUSE_UP, _BtnUp_OnMouseUp);
			_BtnUp.removeEventListener(MouseEvent.MOUSE_OUT, _BtnUp_OnMouseUp);
			
			_BtnDown.removeEventListener(MouseEvent.MOUSE_DOWN, _BtnDown_OnMouseDown);
			_BtnDown.removeEventListener(MouseEvent.MOUSE_UP, _BtnDown_OnMouseUp);
			_BtnDown.removeEventListener(MouseEvent.MOUSE_OUT, _BtnDown_OnMouseUp);
			
			_TimerDown.removeEventListener(TimerEvent.TIMER, _TimerDown_OnTimer);
			_TimerUp.removeEventListener(TimerEvent.TIMER, _TimerUp_OnTimer);
			
			_Input.$TextUi.removeEventListener(Event.CHANGE, _Input_OnChange);
			
			_BtnDown.$Disable();
			_BtnUp.$Disable();
			_Input.$Disable();
		}
		
		override public function set width ( p_width:Number ) : void {
			_Input.width = p_width - _BtnDown.width;
			_Recolocate();
		}
		
		public function  get $Settings () : Object {
			return _Settings;
		}
		
		/**
		 * Añade settings al objeto
		 */
		public function  set $Settings ( p_settings:Object ) : void {
			ObjectUtil.$Merge(p_settings, _Settings);
			
			if (     p_settings["restringedValues"] != null
			     && (p_settings["restringedValues"]["minValue"] != null || p_settings["restringedValues"]["maxValue"] != null)
			) {
				_CheckRestringedValues();
			}
		}
	}
	
}